﻿using System;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Derbster.Domain.Test
{
    [TestClass]
    public class JamLineupUnitTest : ContractUnitTest
    {
        private Match _testMatch;
        private CommandManager _commandManager;

        [TestInitialize]
        public void TestSetup()
        {
            _testMatch = TestHelper.CreateTestMatch(true, true, "TestMatch");
            _commandManager = new CommandManager();
            _commandManager.Clear();
        }

        [TestMethod]
        public void TestAddFirstJammer()
        {
            _testMatch.BeginMatch();
            _testMatch.BeginPeriod();

            // Add a blocker to test code that checks if jammer is not blocker.
            var player2 = _testMatch.FirstTeamRoster.Players.Skip(3).First();
            _testMatch.CurrentJam.AddFirstTeamBlocker(player2);
            var player = _testMatch.FirstTeamRoster.Players.Skip(1).First();
            _testMatch.CurrentJam.AddFirstTeamJammer(player);
            Assert.IsTrue(_testMatch.CurrentJam.FirstTeamLineup.Jammer == player);
            _commandManager.Undo();
            Assert.IsNull(_testMatch.CurrentJam.FirstTeamLineup.Jammer);
            _commandManager.Redo();
            Assert.IsTrue(_testMatch.CurrentJam.FirstTeamLineup.Jammer == player);
        }

        [TestMethod]
        public void TestAddSecondJammer()
        {
            _testMatch.BeginMatch();
            _testMatch.BeginPeriod();

            // Add a blocker to test code that checks if jammer is not blocker.
            var player2 = _testMatch.SecondTeamRoster.Players.Skip(3).First();
            _testMatch.CurrentJam.AddSecondTeamBlocker(player2);           
            var player = _testMatch.SecondTeamRoster.Players.Skip(1).First();
            _testMatch.CurrentJam.AddSecondTeamJammer(player);
            Assert.IsTrue(_testMatch.CurrentJam.SecondTeamLineup.Jammer == player);
            _commandManager.Undo();
            Assert.IsNull(_testMatch.CurrentJam.SecondTeamLineup.Jammer);
            _commandManager.Redo();
            Assert.IsTrue(_testMatch.CurrentJam.SecondTeamLineup.Jammer == player);
        }

        [TestMethod]
        public void TestAddFirstPivot()
        {
            _testMatch.BeginMatch();
            _testMatch.BeginPeriod();

            // Add a blocker to test code that checks if pivot is not blocker.
            var player2 = _testMatch.FirstTeamRoster.Players.Skip(3).First();
            _testMatch.CurrentJam.AddFirstTeamBlocker(player2);
            var player = _testMatch.FirstTeamRoster.Players.Skip(1).First();
            _testMatch.CurrentJam.AddFirstTeamPivot(player);
            Assert.IsTrue(_testMatch.CurrentJam.FirstTeamLineup.Pivot == player);
            _commandManager.Undo();
            Assert.IsNull(_testMatch.CurrentJam.FirstTeamLineup.Pivot);
            _commandManager.Redo();
            Assert.IsTrue(_testMatch.CurrentJam.FirstTeamLineup.Pivot == player);
        }

        [TestMethod]
        public void TestAddSecondPivot()
        {
            _testMatch.BeginMatch();
            _testMatch.BeginPeriod();

            // Add a blocker to test code that checks if pivot is not blocker.
            var player2 = _testMatch.SecondTeamRoster.Players.Skip(3).First();
            _testMatch.CurrentJam.AddSecondTeamBlocker(player2);
            var player = _testMatch.SecondTeamRoster.Players.Skip(1).First();
            _testMatch.CurrentJam.AddSecondTeamPivot(player);
            Assert.IsTrue(_testMatch.CurrentJam.SecondTeamLineup.Pivot == player);
            _commandManager.Undo();
            Assert.IsNull(_testMatch.CurrentJam.SecondTeamLineup.Pivot);
            _commandManager.Redo();
            Assert.IsTrue(_testMatch.CurrentJam.SecondTeamLineup.Pivot == player);
        }

        [TestMethod]
        public void TestAddFirstBlocker()
        {
            _testMatch.BeginMatch();
            _testMatch.BeginPeriod();

            // Add a blocker to test code that checks if added blocker is not existing blocker.
            var player2 = _testMatch.FirstTeamRoster.Players.Skip(3).First();
            _testMatch.CurrentJam.AddFirstTeamBlocker(player2);
            var player = _testMatch.FirstTeamRoster.Players.Skip(1).First();
            _testMatch.CurrentJam.AddFirstTeamBlocker(player);
            Assert.IsTrue(_testMatch.CurrentJam.FirstTeamLineup.Blockers.Contains(player));
            _commandManager.Undo();
            Assert.IsFalse(_testMatch.CurrentJam.FirstTeamLineup.Blockers.Contains(player));
            _commandManager.Redo();
            Assert.IsTrue(_testMatch.CurrentJam.FirstTeamLineup.Blockers.Contains(player));
        }

        [TestMethod]
        public void TestAddSecondBlocker()
        {
            _testMatch.BeginMatch();
            _testMatch.BeginPeriod();

            // Add a blocker to test code that checks if added blocker is not existing blocker.
            var player2 = _testMatch.SecondTeamRoster.Players.Skip(3).First();
            _testMatch.CurrentJam.AddSecondTeamBlocker(player2);
            var player = _testMatch.SecondTeamRoster.Players.Skip(1).First();
            _testMatch.CurrentJam.AddSecondTeamBlocker(player);
            Assert.IsTrue(_testMatch.CurrentJam.SecondTeamLineup.Blockers.Contains(player));
            _commandManager.Undo();
            Assert.IsFalse(_testMatch.CurrentJam.SecondTeamLineup.Blockers.Contains(player));
            _commandManager.Redo();
            Assert.IsTrue(_testMatch.CurrentJam.SecondTeamLineup.Blockers.Contains(player));
        }

        [TestMethod]
        public void TestAddAndCorrectFirstJammer()
        {
            _testMatch.BeginMatch();
            _testMatch.BeginPeriod();
            var player = _testMatch.FirstTeamRoster.Players.Skip(1).First();
            var player2 = _testMatch.FirstTeamRoster.Players.Skip(3).First();

            // Add a blocker to test code that checks corrected jammer is not existing blocker.
            var player3 = _testMatch.FirstTeamRoster.Players.Skip(6).First();
            _testMatch.CurrentJam.AddFirstTeamBlocker(player3);
            _testMatch.CurrentJam.AddFirstTeamJammer(player);
            _testMatch.CurrentJam.CorrectFirstTeamLineup(player, player2);
            Assert.IsTrue(_testMatch.CurrentJam.FirstTeamLineup.Jammer == player2);
            _commandManager.Undo();
            Assert.IsTrue(_testMatch.CurrentJam.FirstTeamLineup.Jammer == player);
            // ReSharper disable HeuristicUnreachableCode
            _commandManager.Redo();
            Assert.IsTrue(_testMatch.CurrentJam.FirstTeamLineup.Jammer == player2);
            // ReSharper restore HeuristicUnreachableCode
        }

        [TestMethod]
        public void TestAddAndCorrectSecondJammer()
        {
            _testMatch.BeginMatch();
            _testMatch.BeginPeriod();
            var player = _testMatch.SecondTeamRoster.Players.Skip(1).First();
            var player2 = _testMatch.SecondTeamRoster.Players.Skip(3).First();
            // Add a blocker to test code that checks corrected jammer is not existing blocker.
            var player3 = _testMatch.SecondTeamRoster.Players.Skip(6).First();
            _testMatch.CurrentJam.AddSecondTeamBlocker(player3);
            _testMatch.CurrentJam.AddSecondTeamJammer(player);
            _testMatch.CurrentJam.CorrectSecondTeamLineup(player, player2);
            Assert.IsTrue(_testMatch.CurrentJam.SecondTeamLineup.Jammer == player2);
            _commandManager.Undo();
            Assert.IsTrue(_testMatch.CurrentJam.SecondTeamLineup.Jammer == player);
            // ReSharper disable HeuristicUnreachableCode
            _commandManager.Redo();
            Assert.IsTrue(_testMatch.CurrentJam.SecondTeamLineup.Jammer == player2);
            // ReSharper restore HeuristicUnreachableCode
        }

        [TestMethod]
        public void TestAddAndCorrectFirstPivot()
        {
            _testMatch.BeginMatch();
            _testMatch.BeginPeriod();
            var player = _testMatch.FirstTeamRoster.Players.Skip(1).First();
            var player2 = _testMatch.FirstTeamRoster.Players.Skip(3).First();
            // Add a blocker to test code that checks corrected pivot is not existing blocker.
            var player3 = _testMatch.FirstTeamRoster.Players.Skip(6).First();
            _testMatch.CurrentJam.AddFirstTeamBlocker(player3);
            _testMatch.CurrentJam.AddFirstTeamPivot(player);
            _testMatch.CurrentJam.CorrectFirstTeamLineup(player, player2);
            Assert.IsTrue(_testMatch.CurrentJam.FirstTeamLineup.Pivot == player2);
            _commandManager.Undo();
            Assert.IsTrue(_testMatch.CurrentJam.FirstTeamLineup.Pivot == player);
            // ReSharper disable HeuristicUnreachableCode
            _commandManager.Redo();
            Assert.IsTrue(_testMatch.CurrentJam.FirstTeamLineup.Pivot == player2);
            // ReSharper restore HeuristicUnreachableCode
        }

        [TestMethod]
        public void TestAddAndCorrectSecondPivot()
        {
            _testMatch.BeginMatch();
            _testMatch.BeginPeriod();
            var player = _testMatch.SecondTeamRoster.Players.Skip(1).First();
            var player2 = _testMatch.SecondTeamRoster.Players.Skip(3).First();
            // Add a blocker to test code that checks corrected pivot is not existing blocker.
            var player3 = _testMatch.SecondTeamRoster.Players.Skip(6).First();
            _testMatch.CurrentJam.AddSecondTeamBlocker(player3);
            _testMatch.CurrentJam.AddSecondTeamPivot(player);
            _testMatch.CurrentJam.CorrectSecondTeamLineup(player, player2);
            Assert.IsTrue(_testMatch.CurrentJam.SecondTeamLineup.Pivot == player2);
            _commandManager.Undo();
            Assert.IsTrue(_testMatch.CurrentJam.SecondTeamLineup.Pivot == player);
            // ReSharper disable HeuristicUnreachableCode
            _commandManager.Redo();
            Assert.IsTrue(_testMatch.CurrentJam.SecondTeamLineup.Pivot == player2);
            // ReSharper restore HeuristicUnreachableCode
        }

        [TestMethod]
        public void TestAddAndCorrectFirstBlocker()
        {
            _testMatch.BeginMatch();
            _testMatch.BeginPeriod();
            var player = _testMatch.FirstTeamRoster.Players.Skip(1).First();
            var player2 = _testMatch.FirstTeamRoster.Players.Skip(3).First();
            // Add a blocker to test code that checks corrected blocker is not existing blocker.
            var player3 = _testMatch.FirstTeamRoster.Players.Skip(6).First();
            _testMatch.CurrentJam.AddFirstTeamBlocker(player3);
            _testMatch.CurrentJam.AddFirstTeamBlocker(player);
            _testMatch.CurrentJam.CorrectFirstTeamLineup(player, player2);
            Assert.IsTrue(_testMatch.CurrentJam.FirstTeamLineup.Blockers.Contains(player2));
            Assert.IsFalse(_testMatch.CurrentJam.FirstTeamLineup.Blockers.Contains(player));
            _commandManager.Undo();
            Assert.IsTrue(_testMatch.CurrentJam.FirstTeamLineup.Blockers.Contains(player));
            Assert.IsFalse(_testMatch.CurrentJam.FirstTeamLineup.Blockers.Contains(player2));
            // ReSharper disable HeuristicUnreachableCode
            _commandManager.Redo();
            Assert.IsTrue(_testMatch.CurrentJam.FirstTeamLineup.Blockers.Contains(player2));
            Assert.IsFalse(_testMatch.CurrentJam.FirstTeamLineup.Blockers.Contains(player));
            // ReSharper restore HeuristicUnreachableCode
        }
        
        [TestMethod]
        public void TestAddAndCorrectSecondBlocker()
        {
            _testMatch.BeginMatch();
            _testMatch.BeginPeriod();
            var player = _testMatch.SecondTeamRoster.Players.Skip(1).First();
            var player2 = _testMatch.SecondTeamRoster.Players.Skip(3).First();
            _testMatch.CurrentJam.AddSecondTeamBlocker(player);
            // Add a blocker to test code that checks corrected blocker is not existing blocker.
            var player3 = _testMatch.SecondTeamRoster.Players.Skip(6).First();
            _testMatch.CurrentJam.AddSecondTeamBlocker(player3);
            _testMatch.CurrentJam.CorrectSecondTeamLineup(player, player2);
            Assert.IsTrue(_testMatch.CurrentJam.SecondTeamLineup.Blockers.Contains(player2));
            Assert.IsFalse(_testMatch.CurrentJam.SecondTeamLineup.Blockers.Contains(player));
            _commandManager.Undo();
            Assert.IsTrue(_testMatch.CurrentJam.SecondTeamLineup.Blockers.Contains(player));
            Assert.IsFalse(_testMatch.CurrentJam.SecondTeamLineup.Blockers.Contains(player2));
            // ReSharper disable HeuristicUnreachableCode
            _commandManager.Redo();
            Assert.IsTrue(_testMatch.CurrentJam.SecondTeamLineup.Blockers.Contains(player2));
            Assert.IsFalse(_testMatch.CurrentJam.SecondTeamLineup.Blockers.Contains(player));
            // ReSharper restore HeuristicUnreachableCode
        }

        [TestMethod]
        public void TestAddAndCorrectFirstBlockerExisting()
        {
            bool throws = false;
            _testMatch.BeginMatch();
            _testMatch.BeginPeriod();
            var player = _testMatch.FirstTeamRoster.Players.Skip(1).First();
            var player2 = _testMatch.FirstTeamRoster.Players.Skip(3).First();
            // Add a blocker to test code that checks corrected blocker is not existing blocker.
            var player3 = _testMatch.FirstTeamRoster.Players.Skip(6).First();
            _testMatch.CurrentJam.AddFirstTeamBlocker(player3);
            _testMatch.CurrentJam.AddFirstTeamBlocker(player2);
            _testMatch.CurrentJam.AddFirstTeamBlocker(player);
            try
            {
                _testMatch.CurrentJam.CorrectFirstTeamLineup(player, player2);
            }
            catch
            {
                throws = true;
            }
            Assert.IsTrue(throws);
        }

        [TestMethod]
        public void TestAddAndCorrectSecondBlockerExisting()
        {
            bool throws = false;
            _testMatch.BeginMatch();
            _testMatch.BeginPeriod();
            var player = _testMatch.SecondTeamRoster.Players.Skip(1).First();
            var player2 = _testMatch.SecondTeamRoster.Players.Skip(3).First();
            // Add a blocker to test code that checks corrected blocker is not existing blocker.
            var player3 = _testMatch.SecondTeamRoster.Players.Skip(6).First();
            _testMatch.CurrentJam.AddSecondTeamBlocker(player3);
            _testMatch.CurrentJam.AddSecondTeamBlocker(player2);
            _testMatch.CurrentJam.AddSecondTeamBlocker(player);
            try
            {
                _testMatch.CurrentJam.CorrectSecondTeamLineup(player, player3);
            }
            catch
            {
                throws = true;
            }
            Assert.IsTrue(throws);
        }


        [TestMethod]
        public void TestAddAndRemoveFirstJammer()
        {
            _testMatch.BeginMatch();
            _testMatch.BeginPeriod();
            var player = _testMatch.FirstTeamRoster.Players.Skip(1).First();
            _testMatch.CurrentJam.AddFirstTeamJammer(player);
            _testMatch.CurrentJam.RemoveFromFirstTeamLineup(player);
            Assert.IsNull(_testMatch.CurrentJam.FirstTeamLineup.Jammer);
            _commandManager.Undo();
            Assert.IsTrue(_testMatch.CurrentJam.FirstTeamLineup.Jammer == player);
            _commandManager.Redo();
            Assert.IsNull(_testMatch.CurrentJam.FirstTeamLineup.Jammer);
        }

        [TestMethod]
        public void TestAddAndRemoveSecondJammer()
        {
            _testMatch.BeginMatch();
            _testMatch.BeginPeriod();
            var player = _testMatch.SecondTeamRoster.Players.Skip(1).First();
            _testMatch.CurrentJam.AddSecondTeamJammer(player);
            _testMatch.CurrentJam.RemoveFromSecondTeamLineup(player);
            Assert.IsNull(_testMatch.CurrentJam.SecondTeamLineup.Jammer);
            _commandManager.Undo();
            Assert.IsTrue(_testMatch.CurrentJam.SecondTeamLineup.Jammer == player);
            _commandManager.Redo();
            Assert.IsNull(_testMatch.CurrentJam.SecondTeamLineup.Jammer);
        }

        [TestMethod]
        public void TestAddAndRemoveFirstPivot()
        {
            _testMatch.BeginMatch();
            _testMatch.BeginPeriod();
            var player = _testMatch.FirstTeamRoster.Players.Skip(1).First();
            _testMatch.CurrentJam.AddFirstTeamPivot(player);
            _testMatch.CurrentJam.RemoveFromFirstTeamLineup(player);
            Assert.IsNull(_testMatch.CurrentJam.FirstTeamLineup.Pivot);
            _commandManager.Undo();
            Assert.IsTrue(_testMatch.CurrentJam.FirstTeamLineup.Pivot == player);
            _commandManager.Redo();
            Assert.IsNull(_testMatch.CurrentJam.FirstTeamLineup.Pivot);
        }

        [TestMethod]
        public void TestAddAndRemoveSecondPivot()
        {
            _testMatch.BeginMatch();
            _testMatch.BeginPeriod();
            var player = _testMatch.SecondTeamRoster.Players.Skip(1).First();
            _testMatch.CurrentJam.AddSecondTeamPivot(player);
            _testMatch.CurrentJam.RemoveFromSecondTeamLineup(player);
            Assert.IsNull(_testMatch.CurrentJam.SecondTeamLineup.Pivot);
            _commandManager.Undo();
            Assert.IsTrue(_testMatch.CurrentJam.SecondTeamLineup.Pivot == player);
            _commandManager.Redo();
            Assert.IsNull(_testMatch.CurrentJam.SecondTeamLineup.Pivot);
        }

        [TestMethod]
        public void TestAddAndRemoveFirstBlocker()
        {
            _testMatch.BeginMatch();
            _testMatch.BeginPeriod();
            var player = _testMatch.FirstTeamRoster.Players.Skip(1).First();
            _testMatch.CurrentJam.AddFirstTeamBlocker(player);
            _testMatch.CurrentJam.RemoveFromFirstTeamLineup(player);
            Assert.IsFalse(_testMatch.CurrentJam.FirstTeamLineup.Blockers.Contains(player));
            _commandManager.Undo();
            Assert.IsTrue(_testMatch.CurrentJam.FirstTeamLineup.Blockers.Contains(player));
            _commandManager.Redo();
            Assert.IsFalse(_testMatch.CurrentJam.FirstTeamLineup.Blockers.Contains(player));
        }

        [TestMethod]
        public void TestAddAndRemoveSecondBlocker()
        {
            _testMatch.BeginMatch();
            _testMatch.BeginPeriod();
            var player = _testMatch.SecondTeamRoster.Players.Skip(1).First();
            _testMatch.CurrentJam.AddSecondTeamBlocker(player);
            _testMatch.CurrentJam.RemoveFromSecondTeamLineup(player);
            Assert.IsFalse(_testMatch.CurrentJam.SecondTeamLineup.Blockers.Contains(player));
            _commandManager.Undo();
            Assert.IsTrue(_testMatch.CurrentJam.SecondTeamLineup.Blockers.Contains(player));
            _commandManager.Redo();
            Assert.IsFalse(_testMatch.CurrentJam.SecondTeamLineup.Blockers.Contains(player));
        }


    }
}
